﻿using DotNetty.Buffers;
using DotNetty.Codecs.Http.WebSockets;
using DotNetty.Handlers.Timeout;
using DotNetty.Transport.Channels;

namespace DotNetty.Extensions
{
    class WebSocketServerHandler : SimpleChannelInboundHandler<WebSocketFrame>
    {
        private readonly WebSocketServer _server;

        public WebSocketServerHandler(WebSocketServer server)
        {
            _server = server;
        }

        //public override void ChannelActive(IChannelHandlerContext context)
        //{
        //    _server.ClientConnected(context);
        //}

        protected override void ChannelRead0(IChannelHandlerContext context, WebSocketFrame frame)
        {
            if (frame is TextWebSocketFrame textFrame)
            {
                _server.ClientTextMessage(context, textFrame.Text());
                return;
            }

            if (frame is BinaryWebSocketFrame)
            {
                _server.ClientBinaryMessage(context, frame.Content.ToBytes());
                return;
            }

            if (frame is PingWebSocketFrame)
            {
                context.WriteAndFlushAsync(new PongWebSocketFrame((IByteBuffer)frame.Content.Retain()));
                return;
            }

            if (frame is CloseWebSocketFrame)
            {
                context.CloseAsync();
                return;
            }
        }

        public override void ChannelReadComplete(IChannelHandlerContext context) => context.Flush();

        public override void ExceptionCaught(IChannelHandlerContext context, Exception e)
        {
            context.CloseAsync();
            _server.ClientException(context, e);
        }

        public override void ChannelInactive(IChannelHandlerContext context)
        {
            _server.ClientDisconnected(context);
        }

        public override void UserEventTriggered(IChannelHandlerContext context, object evt)
        {
            if (evt is IdleStateEvent eventState)
            {
                if (eventState != null)
                {
                    context.Channel.CloseAsync();
                }

                return;
            }

            if (evt is WebSocketServerProtocolHandler.HandshakeComplete)
            {
                _server.ClientConnected(context); //握手成功才表示连接成功
                return;
            }
        }
    }
}
